//
//  ObservableExtend.swift
//  mycloudmusicswift
//
//  Created by smile on 2019/5/3.
//  Copyright © 2019 ixuea. All rights reserved.
//

import UIKit

//导入响应式编程框架
import RxSwift

//JSON解析为对象
import HandyJSON

// 导入网络框架
import Moya

/// 自定义一个错误
/// 他是一个枚举
///
/// - objectMapping: <#objectMapping description#>
public enum IxueaError : Swift.Error {
    case objectMapping
}

// MARK: - 扩展Observable
extension Observable {
    
    /// 将字符串转为对象
    ///
    /// - Parameter type: 要转为的类
    /// - Returns: 转换完成的对象
    public func mapObject<T: HandyJSON>(_ type: T.Type) -> Observable<T?>{
        
        return self.map { data in
            //将输入参数转为字符串
            guard let dataString=data as? String else {
                //如果数据不能转为字符串
                //就返回nil
                return nil
            }
            
            if dataString.isEmpty {
                //空字符串也返回nil
                return nil
            }
            
            guard let result = type.deserialize(from: dataString) else {
                //转为对象失败
                //抛出错误
                throw IxueaError.objectMapping
            }
            
            //返回解析后的对象
            return result
        }
        
    }

}

/// http网络请求观察者
public class HttpObserver<Element> : ObserverType {
    /// ObserverType协议里面用到了E泛型
    /// 所以子类要通过别名指定
    /// 不然会报错
    public typealias E = Element
    
    /// 请求正确回调
    var onSuccess: ((E) -> Void)
    
    /// 出错了回调
    var onError: ((BaseResponse?,Error?) -> Bool)?
    
    /// 初始化方法
    ///
    /// - Parameters:
    ///   - onSuccess: 请求正确回调
    ///   - onError: 出错了回调
    init(_ onSuccess: @escaping ((E) -> Void),_ onError: ((BaseResponse?,Error?) -> Bool)?) {
        self.onSuccess=onSuccess
        self.onError=onError
    }
    
    /// 当RxSwift中发生了实现回调
    ///
    /// - Parameter event: 事件镀锡
    public func on(_ event: Event<Element>) {
        switch event {
        case .next(let value):
            //next事件
            print("HttpObserver next:\(value)")
            
            //将值转为BaseResponse
            let baseResponse=value as? BaseResponse
            
            if let _ = baseResponse?.status{
                //有状态码表示请求出错了
                requestErrorHandler(baseResponse: baseResponse)
            }else{
                //请求正常
                onSuccess(value)
            }
            
        case .error(let error):
            //错误事件
            print("HttpObserver onError:\(error)")
            
            //有错误信息也是请求出错了
            requestErrorHandler(error: error)
            
        case .completed:
            //完成事件
            print("HttpObserver completed")
        }
    }
    
    /// 处理请求错误
    ///
    /// - Parameters:
    ///   - baseResponse: 请求返回的对象
    ///   - error: 错误信息
    func requestErrorHandler( baseResponse:BaseResponse?=nil,error:Swift.Error?=nil) {
        if onError != nil && onError!(baseResponse,error) {
            //回调失败方法
            //返回YES，父类不自动处理错误
            
            //子类需要关闭loading，当前也可以父类关闭
            //暴露给子类的原因是，有些场景会用到
            //例如：请求失败后，在调用一个接口，如果中途关闭了
            //用户能看到多次显示loading，体验没那么好
        }else{
            //自动处理错误
           
            //继续进行错误处理
            HttpUtil.handlerRequest(baseResponse: baseResponse, error: error)

        }
    }
}

// MARK: - 扩展ObservableType
extension ObservableType {
  
    /// 观察成功和失败事件
    ///
    /// - Parameters:
    ///   - onSuccess: 请求正确回调
    ///   - onError: 出错了回调
    /// - Returns: <#return value description#>
    func subscribe(_ onSuccess: @escaping ((E) -> Void),_ onError: @escaping ((BaseResponse?,Error?) -> Bool))
        -> Disposable {
            let disposable = Disposables.create()
            
            //初始化一个HttpObserver
            //将回调事件传递到这里面了
            let observer=HttpObserver<E>(onSuccess,onError)

            //创建并返回了Disposables对象
            //实现的效果是当发生一系列事件时
            //就会回调到HttpObserver的on方法
            return Disposables.create(
                self.asObservable().subscribe(observer),
                disposable
            )
    }

    /// <#Description#>
    ///
    /// - Parameter onSuccess: 请求正确回调
    /// - Returns: <#return value description#>
    func subscribeOnSuccess(_ onSuccess: @escaping ((E) -> Void))
        -> Disposable {
            let disposable = Disposables.create()
            
            let observer=HttpObserver<E>(onSuccess,nil)
            
            
            return Disposables.create(
                self.asObservable().subscribe(observer),
                disposable
            )
    }
}

